home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1999 March / EnigmA AMIGA RUN 35 (1999)(G.R. Edizioni)(IT)[!][issue 1999-03].iso / earcd / devel / vbcc-src / vcpp / cpp.c next >
C/C++ Source or Header  |  1999-01-01  |  10KB  |  322 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <time.h>
  5. #include <stdarg.h>
  6. #include "cpp.h"
  7.  
  8. #define OUTS    16384
  9. char    outbuf[OUTS];
  10. char    *outp = outbuf;
  11. Source  *cursource;
  12. int     nerrs;
  13. struct  token nltoken = { NL, 0, 0, 0, 1, (uchar*)"\n" };
  14. char    *curtime;
  15. int     incdepth;
  16. int     ifdepth;
  17. int     ifsatisfied[NIF];
  18. int     skipping;
  19.  
  20. char rcsid[] = "$Revision: 1.5 $ $Date: 1994/12/01 14:48:55 $";
  21.  
  22. int
  23. main(int argc, char **argv)
  24. {
  25.         Tokenrow tr;
  26.         time_t t;
  27.         char ebuf[BUFSIZ];
  28.  
  29. /*vb:        setbuf(stderr, ebuf);*/
  30.         t = time(NULL);
  31.         curtime = ctime(&t);
  32.         maketokenrow(3, &tr);
  33.         expandlex();
  34.         setup(argc, argv);
  35.         fixlex();
  36.         iniths();
  37.         genline();
  38.         process(&tr);
  39.         flushout();
  40.         fflush(stderr);
  41.         exit(nerrs > 0);
  42.         return 0;
  43. }
  44.  
  45. void
  46. process(Tokenrow *trp)
  47. {
  48.         int anymacros = 0;
  49.  
  50.         for (;;) {
  51.                 if (trp->tp >= trp->lp) {
  52.                         trp->tp = trp->lp = trp->bp;
  53.                         outp = outbuf;
  54.                         anymacros |= gettokens(trp, 1);
  55.                         trp->tp = trp->bp;
  56.                 }
  57.                 if (trp->tp->type == END) {
  58.                         if (--incdepth>=0) {
  59.                                 if (cursource->ifdepth)
  60.                                         error(ERROR,
  61.                                          "Unterminated conditional in #include");
  62.                                 unsetsource();
  63.                                 cursource->line += cursource->lineinc;
  64.                                 trp->tp = trp->lp;
  65.                                 genline();
  66.                                 continue;
  67.                         }
  68.                         if (ifdepth)
  69.                                 error(ERROR, "Unterminated #if/#ifdef/#ifndef");
  70.                         break;
  71.                 }
  72.                 if (trp->tp->type==SHARP) {
  73.                         trp->tp += 1;
  74.                         control(trp);
  75.                 } else if (!skipping && anymacros)
  76.                         expandrow(trp, NULL);
  77.                 if (skipping)
  78.                         setempty(trp);
  79.                 puttokens(trp);
  80.                 anymacros = 0;
  81.                 cursource->line += cursource->lineinc;
  82.                 if (cursource->lineinc>1) {
  83.                         genline();
  84.                 }
  85.         }
  86. }
  87.  
  88. void
  89. control(Tokenrow *trp)
  90. {
  91.         Nlist *np;
  92.         Token *tp;
  93.  
  94.         tp = trp->tp;
  95.         if (tp->type!=NAME) {
  96.                 if (tp->type==NUMBER)
  97.                         goto kline;
  98.                 if (tp->type != NL)
  99.                         error(ERROR, "Unidentifiable control line");
  100.                 return;                 /* else empty line */
  101.         }
  102.         if ((np = lookup(tp, 0))==NULL || (np->flag&ISKW)==0 && !skipping) {
  103.                 error(WARNING, "Unknown preprocessor control %t", tp);
  104.                 return;
  105.         }
  106.         if (skipping) {
  107.                 switch (np->val) {
  108.                 case KENDIF:
  109.                         if (--ifdepth<skipping)
  110.                                 skipping = 0;
  111.                         --cursource->ifdepth;
  112.                         setempty(trp);
  113.                         return;
  114.  
  115.                 case KIFDEF:
  116.                 case KIFNDEF:
  117.                 case KIF:
  118.                         if (++ifdepth >= NIF)
  119.                                 error(FATAL, "#if too deeply nested");
  120.                         ++cursource->ifdepth;
  121.                         return;
  122.  
  123.                 case KELIF:
  124.                 case KELSE:
  125.                         if (ifdepth<=skipping)
  126.                                 break;
  127.                         return;
  128.  
  129.                 default:
  130.                         return;
  131.                 }
  132.         }
  133.         switch (np->val) {
  134.         case KDEFINE:
  135.                 dodefine(trp);
  136.                 break;
  137.  
  138.         case KUNDEF:
  139.                 tp += 1;
  140.                 if (tp->type!=NAME || trp->lp - trp->bp != 4) {
  141.                         error(ERROR, "Syntax error in #undef");
  142.                         break;
  143.                 }
  144.                 if ((np = lookup(tp, 0)) != NULL)
  145.                         np->flag &= ~ISDEFINED;
  146.                 break;
  147.  
  148.         case KPRAGMA:
  149.                 return;
  150.  
  151.         case KIFDEF:
  152.         case KIFNDEF:
  153.         case KIF:
  154.                 if (++ifdepth >= NIF)
  155.                         error(FATAL, "#if too deeply nested");
  156.                 ++cursource->ifdepth;
  157.                 ifsatisfied[ifdepth] = 0;
  158.                 if (eval(trp, np->val))
  159.                         ifsatisfied[ifdepth] = 1;
  160.                 else
  161.                         skipping = ifdepth;
  162.                 break;
  163.  
  164.         case KELIF:
  165.                 if (ifdepth==0) {
  166.                         error(ERROR, "#elif with no #if");
  167.                         return;
  168.                 }
  169.                 if (ifsatisfied[ifdepth]==2)
  170.                         error(ERROR, "#elif after #else");
  171.                 if (eval(trp, np->val)) {
  172.                         if (ifsatisfied[ifdepth])
  173.                                 skipping = ifdepth;
  174.                         else {
  175.                                 skipping = 0;
  176.                                 ifsatisfied[ifdepth] = 1;
  177.                         }
  178.                 } else
  179.                         skipping = ifdepth;
  180.                 break;
  181.  
  182.         case KELSE:
  183.                 if (ifdepth==0 || cursource->ifdepth==0) {
  184.                         error(ERROR, "#else with no #if");
  185.                         return;
  186.                 }
  187.                 if (ifsatisfied[ifdepth]==2)
  188.                         error(ERROR, "#else after #else");
  189.                 if (trp->lp - trp->bp != 3)
  190.                         error(ERROR, "Syntax error in #else");
  191.                 skipping = ifsatisfied[ifdepth]? ifdepth: 0;
  192.                 ifsatisfied[ifdepth] = 2;
  193.                 break;
  194.  
  195.         case KENDIF:
  196.                 if (ifdepth==0 || cursource->ifdepth==0) {
  197.                         error(ERROR, "#endif with no #if");
  198.                         return;
  199.                 }
  200.                 --ifdepth;
  201.                 --cursource->ifdepth;
  202.                 if (trp->lp - trp->bp != 3)
  203.                         error(WARNING, "Syntax error in #endif");
  204.                 break;
  205.  
  206.         case KERROR:
  207.                 trp->tp = tp+1;
  208.                 error(WARNING, "#error directive: %r", trp);
  209.                 break;
  210.  
  211.         case KLINE:
  212.                 trp->tp = tp+1;
  213.                 expandrow(trp, "<line>");
  214.                 tp = trp->bp+2;
  215.         kline:
  216.                 if (tp+1>=trp->lp || tp->type!=NUMBER || tp+3<trp->lp
  217.                  || (tp+3==trp->lp && ((tp+1)->type!=STRING)||*(tp+1)->t=='L')){
  218.                         error(ERROR, "Syntax error in #line");
  219.                         return;
  220.                 }
  221.                 cursource->line = atol((char*)tp->t)-1;
  222.                 if (cursource->line<0 || cursource->line>=32768)
  223.                         error(WARNING, "#line specifies number out of range");
  224.                 tp = tp+1;
  225.                 if (tp+1<trp->lp)
  226.                         cursource->filename=(char*)newstring(tp->t+1,tp->len-2,0);
  227.                 return;
  228.  
  229.         case KDEFINED:
  230.                 error(ERROR, "Bad syntax for control line");
  231.                 break;
  232.  
  233.         case KINCLUDE:
  234.                 doinclude(trp);
  235.                 trp->lp = trp->bp;
  236.                 return;
  237.  
  238.         case KEVAL:
  239.                 eval(trp, np->val);
  240.                 break;
  241.  
  242.         default:
  243.                 error(ERROR, "Preprocessor control `%t' not yet implemented", tp);
  244.                 break;
  245.         }
  246.         setempty(trp);
  247.         return;
  248. }
  249.  
  250. void *
  251. domalloc(int size)
  252. {
  253.         void *p = malloc(size);
  254.  
  255.         if (p==NULL)
  256.                 error(FATAL, "Out of memory from malloc");
  257.         return p;
  258. }
  259.  
  260. void
  261. dofree(void *p)
  262. {
  263.         free(p);
  264. }
  265.  
  266. void
  267. error(enum errtype type, char *string, ...)
  268. {
  269.         va_list ap;
  270.         char *cp, *ep;
  271.         Token *tp;
  272.         Tokenrow *trp;
  273.         Source *s;
  274.         int i;
  275.  
  276.         fprintf(stderr, "cpp: ");
  277.         for (s=cursource; s; s=s->next)
  278.                 if (*s->filename)
  279.                         fprintf(stderr, "%s:%d ", s->filename, s->line);
  280.         va_start(ap, string);
  281.         for (ep=string; *ep; ep++) {
  282.                 if (*ep=='%') {
  283.                         switch (*++ep) {
  284.  
  285.                         case 's':
  286.                                 cp = va_arg(ap, char *);
  287.                                 fprintf(stderr, "%s", cp);
  288.                                 break;
  289.                         case 'd':
  290.                                 i = va_arg(ap, int);
  291.                                 fprintf(stderr, "%d", i);
  292.                                 break;
  293.                         case 't':
  294.                                 tp = va_arg(ap, Token *);
  295.                                 fprintf(stderr, "%.*s", tp->len, tp->t);
  296.                                 break;
  297.  
  298.                         case 'r':
  299.                                 trp = va_arg(ap, Tokenrow *);
  300.                                 for (tp=trp->tp; tp<trp->lp&&tp->type!=NL; tp++) {
  301.                                         if (tp>trp->tp && tp->wslen)
  302.                                                 fputc(' ', stderr);
  303.                                         fprintf(stderr, "%.*s", tp->len, tp->t);
  304.                                 }
  305.                                 break;
  306.  
  307.                         default:
  308.                                 fputc(*ep, stderr);
  309.                                 break;
  310.                         }
  311.                 } else
  312.                         fputc(*ep, stderr);
  313.         }
  314.         va_end(ap);
  315.         fputc('\n', stderr);
  316.         if (type==FATAL)
  317.                 exit(1);
  318.         if (type!=WARNING)
  319.                 nerrs = 1;
  320.         fflush(stderr);
  321. }
  322.